home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Files / XTND 1.3.6 / Translator Examples / MacWrite Translator / MacWriteExport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-30  |  37.1 KB  |  1,150 lines  |  [TEXT/MPS ]

  1. /************************************************************************
  2. *                                                                        *
  3. *    MacWriteExport.c                                                    *
  4. *                                                                        *
  5. *    Translator for writing a MacWrite file with XTND 1.3.                *
  6. *                                                                        *
  7. *    Copyright © 1989,90 Claris Corporation                                *
  8. *    All Rights Reserved                                                    *
  9. *                                                                        *
  10. *    Author: Richard Scorer                                                *
  11. *    Date:   13 April, 1988                                                *
  12. *                                                                        *
  13. ************************************************************************/
  14.  
  15. #include <Resources.h>
  16. #include <ToolUtils.h>
  17. #include <StandardFile.h>
  18. #include <Memory.h>
  19. #include <Printing.h>
  20. enum { FALSE,TRUE };
  21.  
  22. #ifndef THINK_C
  23. #include "CodeA5Globals.h"
  24. #endif
  25.  
  26. #include ":::XTND Headers:XTNDCIncludes:XTNDTextTranslator.h"    /* XTND Export defs */
  27.  
  28. #include "MacWriteExport.h"                            /* MW 5.0 Export specifics */
  29. #include "MacWrite.h"                                /* MW 5.0 specifics */
  30.  
  31.  
  32. /*------------------------- Useful Constants ---------------------------*/
  33.  
  34. #define    MWFontSizes        6
  35. #define    MWPageHeight    730                /* height of MacWrite page */
  36. #define    MaxHFParas        8                /* max # of paragraphs allowed in a header or footer */
  37. #define    StyleMask        0x007f            /* mask for MoonRaker styles */
  38. /* #define NULL            0L */
  39.  
  40. #define ISLINECHAR(ch) (ch <= returnChar && (ch >= newColumn || ch == hardReturn || ch == mergeBreak))
  41.  
  42. typedef    struct dummy
  43. {
  44.     short    x[5];
  45. } dummy;
  46.  
  47.  
  48. /*-------------------------Global Variables-----------------------------*/
  49.  
  50. static ExportParmBlkPtr        gExportPBPtr;
  51. static MacWriteHdrHandle    MWHeader;
  52.  
  53. static long                gCount;
  54. static Fixed            gOldFmt[numParaFmts];
  55. static TabSpec            gOldTab[10];
  56. static short            gOldJust;
  57. static Boolean            gFirstTime, gNewParagraph, gFirstStyle;
  58.  
  59. static ParagraphHandle    gParaData;
  60. static FormatHandle        gFormatRun;
  61. static LineHandle        gLineData;
  62. static long                gParaLength, gParaStart;
  63. static short            gNumParas, gNumFormats, gTextLength, gPHeight, gRealParas;
  64. static char                MWSizes[MWFontSizes] = {9, 10, 12, 14, 18, 24};
  65. static short            gColumnWidth;
  66.  
  67.  
  68. /*-------------------------Function prototypes--------------------------*/
  69.  
  70.         void    main(ExportParmBlkPtr exportParamPtr);
  71. static void        ExportMacWrite(ExportParmBlkPtr exportParamPtr);
  72. static short    WriteResources(void);
  73. static short    InitAll(void);
  74. static short    InitStory(void);
  75. static Boolean    ChangeParagraph(void);
  76. static short    InsertParagraph(void);
  77. static short    WritePict(void);
  78. static short    WritePageBreak(void);
  79. static short    InsertRuler(void);
  80. static short    FindFontSize(short);
  81. static short    WriteParagraph(void);
  82. static short    WriteCR(void);
  83. static short    LastParagraph(void);
  84. static short    CloseStory(void);
  85. static short    TidyUp(void);
  86.  
  87.  
  88. /*----------------------------------------------------------------------*/
  89. /*                                                                        */
  90. /*    main    This is the main routine and the only entry point for the    */
  91. /*            the translator.                                                */
  92. /*    NOTE: This translator uses globals that are used from the first to    */
  93. /*    last call. Therefore, the global data storage cannot be deallocated    */
  94. /*    when the translator receives the EXPORT_CLOSE_ALL directive.        */
  95. /*    Instead, it must deallocate its global storage when it receives the    */
  96. /*    EXPORT_WRITE_RESOURCES directive. If an exception occurs, causing    */
  97. /*    the application to abort the translation, the translator will never    */
  98. /*    receive the EXPORT_WRITE_RESOURCES directive and its global storage    */
  99. /*    will remain in the heap as useless garbage. Note to this note: this    */
  100. /*    note does NOT apply if you are using Think C’s A4-based globals.    */
  101. /*                                                                        */
  102. /*----------------------------------------------------------------------*/
  103. void main(exportParamPtr)
  104. ExportParmBlkPtr exportParamPtr;
  105. {
  106. #ifdef THINK_C
  107.     asm {
  108.         move.l    a4,-(sp)
  109.         move.l    a0,a4                ; Sets up the globals for this CODE
  110.     }
  111. #else
  112.     long savedA5;
  113.  
  114.     if (exportParamPtr->directive == exportInitAll) {
  115.         exportParamPtr->globalHandle = NewHandle(0L);
  116.         MakeA5World(exportParamPtr->globalHandle);
  117.     }
  118.     savedA5 = SetA5World(exportParamPtr->globalHandle);
  119. #endif
  120.  
  121.     ExportMacWrite(exportParamPtr);
  122.  
  123. #ifdef THINK_C
  124.     asm {
  125.         move.l    (sp)+,a4
  126.     }
  127. #else
  128.     RestoreA5World(savedA5, exportParamPtr->globalHandle);
  129.     if (exportParamPtr->directive == exportWriteResources) {
  130.         DisposeA5World(exportParamPtr->globalHandle);
  131.         exportParamPtr->globalHandle = NULL;
  132.     }
  133. #endif
  134. }
  135.  
  136.  
  137. /*----------------------------------------------------------------------*/
  138. /*                                                                        */
  139. /*    ExportMacWrite dispatches the call to the appropriate routine         */
  140. /*  depending on the Directive.                                            */
  141. /*                                                                        */
  142. /*----------------------------------------------------------------------*/
  143. void ExportMacWrite(register ExportParmBlkPtr exportParamPtr)
  144. {
  145.     gExportPBPtr = exportParamPtr;    /* Save the param block pointer in a global    */
  146.  
  147.     switch (exportParamPtr->directive) {
  148.         case exportInitAll:            /* Initialize the translator.  This must be    */
  149.             InitAll();                /* the first call to the translator.          */
  150.             break;
  151.  
  152.         case exportOpenRightHeader:    /*     Initialize a story.                    */
  153.         case exportOpenHeader:        /*    It could be any of these types        */
  154.         case exportOpenRightFooter:
  155.         case exportOpenFooter:
  156.         case exportOpenMain:
  157.             exportParamPtr->directive = exportAcknowledge;
  158.             InitStory();
  159.             break;
  160.         
  161.         case exportOpenLeftHeader:
  162.             /* Only accept left headers if there are no right headers */
  163.             if (!(exportParamPtr->headerStatus & RightPage)) {
  164.                 exportParamPtr->directive = exportAcknowledge;
  165.                 InitStory();
  166.             }
  167.             break;
  168.         
  169.         case exportOpenLeftFooter:
  170.             /* Only accept left footers if there are no right footers */
  171.             if (!(exportParamPtr->footerStatus & RightPage)) {
  172.                 exportParamPtr->directive = exportAcknowledge;
  173.                 InitStory();
  174.             }
  175.             break;
  176.  
  177.         case exportWriteText:                    /* Write the next text run to the file.    */
  178.             WriteParagraph();
  179.             break;
  180.  
  181.         case exportCloseRightHeader:        /* Close any story when finished    */
  182.         case exportCloseLeftHeader:        /* with it.                            */
  183.         case exportCloseHeader:
  184.         case exportCloseRightFooter:
  185.         case exportCloseLeftFooter:
  186.         case exportCloseFooter:
  187.         case exportCloseMain:
  188.             CloseStory();
  189.             break;
  190.  
  191.         case exportCloseAll:                /* Do required clean up here         */
  192.             TidyUp();
  193.             break;
  194.  
  195.         case exportWriteResources:
  196.             WriteResources();
  197.             break;
  198.             
  199.         default:
  200.             break;
  201.     }
  202. } /* ExportMacWrite */
  203.  
  204.  
  205. /*----------------------------------------------------------------------*/
  206. /*                                                                        */
  207. /*    WriteResources writes certain resources required by MacWrite 5.0    */
  208. /*                                                                        */
  209. /*    We need to write:                                                    */
  210. /*     1. International resource                                            */
  211. /*     2. Compression string (even though we don't use it, MW needs it)    */
  212. /*     3. List of fonts. (not needed)                                        */
  213. /*                                                                        */
  214. /*----------------------------------------------------------------------*/
  215. static short WriteResources()
  216. {
  217.     register Handle        TheData;
  218.     register short        intl;
  219.     short                theID;
  220.     ResType                theType;
  221.     register Str255        theName;
  222.     
  223.     *(gExportPBPtr->result) = noErr;
  224.  
  225.     UseResFile(*(gExportPBPtr->refNum));
  226.     for (intl = 0; intl < 2; intl++) {
  227.         TheData = GetResource('INTL', intl);
  228.         DetachResource(TheData);
  229.  
  230.         AddResource(TheData, 'INTL', intl, (StringPtr)"\p");
  231.         if (*(gExportPBPtr->result) = ResError())  return(*(gExportPBPtr->result));
  232.     }
  233.     TheData = GetResource('STR ', 700);    /* Compression String */
  234.     GetResInfo(TheData, &theID, &theType, theName);
  235.     DetachResource(TheData);
  236.  
  237.     AddResource(TheData, 'STR ', 700, theName);
  238.     if (*(gExportPBPtr->result) = ResError()) return(*(gExportPBPtr->result));
  239.  
  240.     CloseResFile(*(gExportPBPtr->refNum));
  241.  
  242.     return(noErr);    /* To indicate we handled the resources */
  243. }    /*    WriteResources    */
  244.  
  245.  
  246. /*----------------------------------------------------------------------*/
  247. /*                                                                        */
  248. /*    InitAll sets up storage for exporting.                                */
  249. /*                                                                        */
  250. /*----------------------------------------------------------------------*/
  251. static short InitAll()
  252. {
  253.     register short        WindowType;
  254.     LineHeightArray        LHA;
  255.     RulerParagraph        TheRuler;
  256.     InfoStruct            Info[2];
  257.     dummy                para;
  258.  
  259.     /* Set up my globals et al */
  260.     /* Write out the "blank" header for MacWrite files */
  261.  
  262.     gCount = sizeof(MacWriteHeader);
  263.     MWHeader = (MacWriteHdrHandle)NewHandle(gCount);
  264.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  265.  
  266.     (**MWHeader).versionNo        = 6;
  267.     (**MWHeader).headerPars        = 2;
  268.     (**MWHeader).footerPars        = 2;
  269.     (**MWHeader).titlePage        = (gExportPBPtr->titlePage ? 0xFF : 0);
  270.     (**MWHeader).scrapDisplay    = 0;
  271.     (**MWHeader).footerDisplay    = (gExportPBPtr->footerStatus == kNone ? 0 : 0xFF);
  272.     (**MWHeader).headerDisplay    = (gExportPBPtr->headerStatus == kNone ? 0 : 0xFF);
  273.     (**MWHeader).rulersHidden    = 0xFF;    /* MUST BE TRUE!!! or page, date and time are wrong */
  274.     (**MWHeader).activeDoc        = 2;    /* Tell MacWrite that document must be recalced */
  275.     (**MWHeader).startPageNum    = gExportPBPtr->startPageNum;
  276.     
  277.     for (WindowType = AFooter; WindowType <= TheMainDoc; WindowType++) {
  278.         (**MWHeader).window[WindowType].selStartPar = 1;
  279.         (**MWHeader).window[WindowType].selStartCh = 0;
  280.         (**MWHeader).window[WindowType].selEndPar = 1;
  281.         (**MWHeader).window[WindowType].selEndCh = 0;
  282.         (**MWHeader).window[WindowType].vertOffSet = 0;
  283.         (**MWHeader).window[WindowType].need2Redraw = 1;
  284.         (**MWHeader).window[WindowType].infoAryLength = 0x20;
  285.         (**MWHeader).window[WindowType].lineHeightAryLength = 0x6;
  286.         (**MWHeader).window[WindowType].pageNumPos = 0xFFF2001E;
  287.         (**MWHeader).window[WindowType].datePos = 0xFFF200C2;
  288.         (**MWHeader).window[WindowType].timePos = WindowType == TheMainDoc ? 0xFFFFFFFF : 0xFFF20190;
  289.         (**MWHeader).window[WindowType].ovalRedraw = 0xFF;
  290.         (**MWHeader).window[WindowType].lastOval = 0xFF;
  291.         (**MWHeader).window[WindowType].activeStyle = 0x0C00;
  292.         (**MWHeader).window[WindowType].activeFont = 3;
  293.     }
  294.     gColumnWidth = (8 * 72 + 36);        /* Document width = 8 inches * 72 pixels/inch + 1/2 inch */
  295.  
  296.     if (gExportPBPtr->printRecord) {
  297.         PrOpen();
  298.         if (!PrError()) {
  299.             PrValidate(gExportPBPtr->printRecord);
  300.             PrClose();
  301.             gColumnWidth = (**gExportPBPtr->printRecord).rPaper.right - (**gExportPBPtr->printRecord).rPaper.left;
  302.         }
  303.         (**MWHeader).printRecord = **gExportPBPtr->printRecord;
  304.     }
  305.     gColumnWidth -= FixRound(gExportPBPtr->leftMargin + gExportPBPtr->rightMargin);
  306.     
  307.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, *MWHeader)) 
  308.         return(*(gExportPBPtr->result));
  309.  
  310.     /* Write out the dummy Footer paragraph & arrays if appropriate */
  311.     TheRuler.leftMargin = 9;
  312.     TheRuler.rightMargin = 0x1DD;
  313.     TheRuler.justification = 0;
  314.     TheRuler.numTabs = 1;
  315.     TheRuler.lineSpacing = 0;
  316.     TheRuler.lineIndent = 9;
  317.     TheRuler.tabArray[0] = 0x144;
  318.  
  319.     para.x[0] = 0;
  320.     para.x[1] = 6;
  321.     para.x[2] = 0;
  322.     para.x[3] = 0xC00;
  323.     para.x[4] = 3;
  324.  
  325.     LHA.heightInfo[0] = 0;
  326.     LHA.heightInfo[1] = 0;
  327.     LHA.heightInfo[2] = 0;
  328.     LHA.heightInfo[3] = 1;
  329.     LHA.heightInfo[4] = 0x10;
  330.     LHA.heightInfo[5] = 0;
  331.  
  332.     Info[0].paraHeight = 0;
  333.     Info[1].paraHeight = 0x10;
  334.     Info[0].paraPagePosn = Info[1].paraPagePosn = 0;
  335.     Info[0].paraHndl = Info[1].paraHndl = 0L;
  336.     Info[0].Status.justCode = Info[1].Status.justCode = 0;
  337.     Info[0].paraFmt = 0;
  338.     Info[1].paraFmt = 0x3301;
  339.  
  340.     for (WindowType = AFooter; WindowType < TheMainDoc; WindowType++) {
  341.         if ((WindowType == AFooter && (**MWHeader).footerDisplay) ||
  342.                     (WindowType == AHeader && (**MWHeader).headerDisplay))
  343.             continue;
  344.     
  345.         GetEOF(*(gExportPBPtr->refNum), &gParaStart);
  346.         Info[0].Status.paraFilePosn = gParaStart;
  347.  
  348.         /* Make a ruler (0x22 bytes long) */
  349.         gCount = Info[0].paraLen = sizeof(RulerParagraph);
  350.  
  351.         /* write out ruler record */
  352.         if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &TheRuler)) 
  353.             return(*(gExportPBPtr->result));
  354.  
  355.         GetEOF(*(gExportPBPtr->refNum), &gParaStart);
  356.         Info[1].Status.paraFilePosn = gParaStart;
  357.         gCount = Info[1].paraLen = 0xA;
  358.  
  359.         /* write out paragraph data */
  360.         if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, ¶)) 
  361.             return(*(gExportPBPtr->result));
  362.  
  363.         gCount = 6;
  364.         GetEOF(*(gExportPBPtr->refNum), &(**MWHeader).window[WindowType].lineHeightAryPos);
  365.         if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &LHA)) 
  366.             return(*(gExportPBPtr->result));
  367.  
  368.         gCount = 0x20;
  369.         GetEOF(*(gExportPBPtr->refNum), &(**MWHeader).window[WindowType].infoAryPos);
  370.         if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &Info[0])) 
  371.             return(*(gExportPBPtr->result));
  372.     }
  373.     return(noErr);
  374. }    /*    InitAll    */
  375.  
  376.  
  377. /*----------------------------------------------------------------------*/
  378. /*                                                                        */
  379. /*    InitStory sets up a story. This consists of setting up required     */
  380. /*  handles and file info.                                                 */
  381. /*                                                                        */
  382. /*----------------------------------------------------------------------*/
  383. static short InitStory()
  384. {
  385.     GetEOF(*(gExportPBPtr->refNum), &gParaStart); /* position output pointer */
  386.     gFirstTime = gNewParagraph = TRUE;
  387.     gFirstStyle = TRUE;
  388.     gPHeight = gNumFormats = gTextLength = 0;
  389.     gRealParas = gNumParas = gParaLength = 0;
  390.  
  391.     gLineData = (LineHandle)NewHandle(0);        /* Set up for storing line height info */
  392.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  393.     gParaData = (ParagraphHandle)NewHandle(0);    /* Set up for storing paragraph info */
  394.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  395.     gFormatRun = (FormatHandle)NewHandle(0);    /* Set up for storing format info */
  396.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  397.  
  398.     return(noErr);
  399. }
  400.  
  401.  
  402. /*----------------------------------------------------------------------*/
  403. /*                                                                        */
  404. /*    ChangeParagraph handles ruler changes in a paragraph.                */
  405. /*                                                                        */
  406. /*----------------------------------------------------------------------*/
  407. static Boolean ChangeParagraph()
  408. {
  409.     register short        i;
  410.     register Boolean    found_change;
  411.     
  412.     if (!(found_change = gFirstTime)) {            /* Don't bother if this is the first time */
  413.         if (*(gExportPBPtr->txtJust) != gOldJust)
  414.             found_change = TRUE;
  415.  
  416.         if (!found_change) {
  417.             for (i = 0; i < numParaFmts; i++) {    /* Check for paragraph format change */
  418.                 if ((gExportPBPtr->paraFmts)[i] != gOldFmt[i]) {
  419.                     found_change = TRUE;
  420.                     break;
  421.                 }
  422.             }
  423.             if (!found_change) {                /* Check for tab changes */
  424.                 for (i = 0; i < 10; i++) {        /* Go forward to get all tabs */
  425.                     if ((gExportPBPtr->tabs)[i].tabJust != gOldTab[i].tabJust || (gExportPBPtr->tabs)[i].tabIndent != gOldTab[i].tabIndent)
  426.                     {
  427.                         if ((gExportPBPtr->tabs)[i].tabIndent != -1) 
  428.                             found_change = TRUE;
  429.                         break;
  430.                     } else {
  431.                         if ((gExportPBPtr->tabs)[i].tabIndent == -1)    /* Found end of tabs */
  432.                             break;
  433.                     }
  434.                 }
  435.             }
  436.         }
  437.     }
  438.     
  439.     if (found_change) {                            /* Save the new changes for next time */
  440.         gOldJust = *(gExportPBPtr->txtJust);
  441.         for (i = 0; i < numParaFmts; i++)
  442.             gOldFmt[i] = (gExportPBPtr->paraFmts)[i];
  443.  
  444.         for (i = 0; (i < 10) && ((gExportPBPtr->tabs)[i].tabIndent != -1); i++)
  445.             gOldTab[i] = (gExportPBPtr->tabs)[i];
  446.     }
  447.     return(found_change);
  448. }    /*    ChangeParagraph */
  449.  
  450.  
  451. /*----------------------------------------------------------------------*/
  452. /*                                                                        */
  453. /*    InsertParagraph writes out current paragraph run.                     */
  454. /*                                                                        */
  455. /*----------------------------------------------------------------------*/
  456. static short InsertParagraph()
  457. {
  458.     short            pad;
  459.     register short    format_length;
  460.  
  461.     GetEOF(*(gExportPBPtr->refNum), &gCount);        /* Are we on an even word boundary */
  462.     if (gCount & 1) {                                /* Write format run on even word boundary */
  463.         pad = 0xFFFF;
  464.         gCount = 1;
  465.         if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &pad)) 
  466.             return(*(gExportPBPtr->result));
  467.         gParaLength++;
  468.     }
  469.     pad = format_length = GetHandleSize((Handle)gFormatRun);
  470.     
  471.     gCount = 2;
  472.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &pad)) 
  473.         return(*(gExportPBPtr->result));
  474.  
  475.     gCount = format_length;
  476.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, *gFormatRun)) 
  477.         return(*(gExportPBPtr->result));    /* Write the run */
  478.  
  479.     SetHandleSize((Handle)gFormatRun, 0L);        /* Reset for next run */
  480.     gNumFormats = 0;
  481.     
  482.     gParaLength += 2;                            /* Room for format run length bytes */
  483.     
  484.     gNewParagraph = TRUE;
  485.     SetHandleSize((Handle)gParaData, GetHandleSize((Handle)gParaData) + sizeof(ParagraphInfo));
  486.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  487.  
  488.     (*gParaData)[gNumParas].filePos = gParaStart;        /* Where this paragraph started */
  489.     (*gParaData)[gNumParas].ruler = FALSE;                /* Not a ruler record */
  490.     (*gParaData)[gNumParas].length = gParaLength;        /* Text length bytes, text, pad byte, format run */
  491.     (*gParaData)[gNumParas].justification = *(gExportPBPtr->txtJust);
  492.     (*gParaData)[gNumParas].height = gPHeight;
  493.  
  494.     pad = 0;
  495.     if (gNumParas) {
  496.         pad = (*gParaData)[gNumParas - 1].height;
  497.         if (pad < 0) pad = -pad;                        /* pictures have a negative height */
  498.         pad += (*gParaData)[gNumParas - 1].pagePos;
  499.     }
  500.     if (pad < 0 || pad >= MWPageHeight) 
  501.         pad = 0;
  502.     (*gParaData)[gNumParas].pagePos = pad;
  503.     gNumParas++;
  504.  
  505.     SetHandleSize((Handle)gLineData, GetHandleSize((Handle)gLineData) + sizeof(LineInfo));
  506.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  507.  
  508.     (*gLineData)[gRealParas].nBytes = 1;
  509.     (*gLineData)[gRealParas].lHeight = (gPHeight << 8) + gPHeight;
  510.     gRealParas++;
  511.     gPHeight = 0;
  512.     if (*(gExportPBPtr->result) = SetFPos(*(gExportPBPtr->refNum), fsFromMark, -gParaLength)) 
  513.         return(*(gExportPBPtr->result));                    /* Move back to begining of text run */
  514.     
  515.     pad = gTextLength;                                    /* Write text length in front of text run */
  516.     gCount = 2;
  517.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &pad)) 
  518.         return(*(gExportPBPtr->result));
  519.     if (*(gExportPBPtr->result) = SetFPos(*(gExportPBPtr->refNum), fsFromLEOF, 0L)) 
  520.         return(*(gExportPBPtr->result));                    /* Set back to end of file */
  521.     
  522.     gTextLength = 0;
  523.     gParaLength = 0;
  524.     GetEOF(*(gExportPBPtr->refNum), &gParaStart);                                /* For next paragraph */
  525.  
  526.     return(noErr);
  527. }    /*    InsertParagraph    */
  528.  
  529.  
  530. /*----------------------------------------------------------------------*/
  531. /*                                                                        */
  532. /*    WritePict writes out a picture to MacWrite.                            */
  533. /*                                                                        */
  534. /*----------------------------------------------------------------------*/
  535. static short WritePict()
  536. {
  537.     register long picSize = GetHandleSize((Handle)(gExportPBPtr->thePicture));
  538.     register short height, temp;
  539.     Rect destRect;
  540.  
  541.     gTextLength--;    /* Occurence of a floating pict character isn't gCounted in length */
  542.  
  543.     if (picSize > 0x7FFF)    /* MacWrite can't handle pictures greater than 32K */
  544.         return(0);
  545.  
  546.     if (gParaLength) {
  547.         SetHandleSize((Handle)gFormatRun, 0L);            /* Reset for next run */
  548.         gNumFormats = 0;
  549.         gParaLength = 0;
  550.         gTextLength = 0;
  551.         if (*(gExportPBPtr->result) = SetFPos(*(gExportPBPtr->refNum), fsFromStart, gParaStart)) 
  552.             return(*(gExportPBPtr->result));
  553.     }
  554.     temp = 0;
  555.  
  556.     if (gNumParas) {
  557.         temp = (*gParaData)[gNumParas - 1].height;
  558.         if (temp < 0) temp = -temp;                        /* pictures have a negative height */
  559.         temp += (*gParaData)[gNumParas - 1].pagePos;
  560.     }
  561.     if (temp < 0 || temp >= MWPageHeight) 
  562.         temp = 0;
  563.  
  564.     destRect = (gExportPBPtr->pictRect);
  565.     height = destRect.bottom - destRect.top;
  566.     OffsetRect(&destRect,
  567.                -destRect.left + (FixRound((gExportPBPtr->paraFmts)[0] * 10 / 9) + 9),
  568.                -destRect.top + temp);
  569.  
  570.     gCount = sizeof(Rect);
  571.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &destRect)) 
  572.         return(*(gExportPBPtr->result));                    /* Write the destRect */
  573.  
  574.     HLock((Handle)(gExportPBPtr->thePicture));
  575.     gCount = picSize;
  576.     if (gCount & 1) gCount++;
  577.  
  578.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, *(gExportPBPtr->thePicture))) 
  579.         return(*(gExportPBPtr->result));                    /* Write the picture */
  580.     HUnlock((Handle)(gExportPBPtr->thePicture));
  581.     gCount += sizeof(Rect);
  582.     
  583.     SetHandleSize((Handle)gParaData, GetHandleSize((Handle)gParaData) + sizeof(ParagraphInfo));
  584.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  585.  
  586.     (*gParaData)[gNumParas].filePos = gParaStart;        /* Where this paragraph started */
  587.     (*gParaData)[gNumParas].ruler = TRUE;                /* Is a ruler record */
  588.     (*gParaData)[gNumParas].length = -gCount;                /* Size of pict (-ve indicates pict) */
  589.     (*gParaData)[gNumParas].justification = *(gExportPBPtr->txtJust);
  590.     (*gParaData)[gNumParas].height = -height;
  591.     (*gParaData)[gNumParas].pagePos = temp;
  592.  
  593.     gPHeight = 0;
  594.     gNumParas++;
  595.     SetHandleSize((Handle)gLineData, GetHandleSize((Handle)gLineData) + sizeof(LineInfo));
  596.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  597.  
  598.     (*gLineData)[gRealParas].nBytes = 0;                    /* picts have no line height */
  599.     gRealParas++;
  600.     if (*(gExportPBPtr->result) = SetFPos(*(gExportPBPtr->refNum), fsFromLEOF, 0L)) 
  601.         return(*(gExportPBPtr->result));                /* Set back to end of file */
  602.     
  603.     gTextLength = 0;
  604.     gParaLength = 0;
  605.     gNewParagraph = TRUE;
  606.     GetEOF(*(gExportPBPtr->refNum), &gParaStart);        /* For next paragraph */
  607.  
  608.     return(noErr);
  609. }    /*    WritePict    */
  610.  
  611.  
  612. /*----------------------------------------------------------------------*/
  613. /*                                                                        */
  614. /*    WritePageBreak writes out a page break to MacWrite. A page break    */
  615. /*  is a special picture paragraph, which has 'MAGICPIC' as the         */
  616. /*  coordinates of the quickdraw rectangle                                */
  617. /*                                                                        */
  618. /*----------------------------------------------------------------------*/
  619. static short WritePageBreak()
  620. {
  621.     Rect                MAGICPIC;
  622.     register PicHandle    PH;
  623.     register short        height, temp;
  624.     PictureParagraph    PB;
  625.  
  626.     /*
  627.         If there is a partial paragraph with real text in it, ie not just a format
  628.         run - write it out.
  629.     */
  630.  
  631.     gTextLength--;    /* Occurrence of a page break character isn't gCounted in length */
  632.     if (gParaLength > 2 + sizeof(FormatInfo))
  633.         InsertParagraph();
  634.     else {
  635.         if (gParaLength) {
  636.             SetHandleSize((Handle)gFormatRun, 0L);        /* Reset for next run */
  637.             gNumFormats = 0;
  638.             gParaLength = 0;
  639.             gTextLength = 0;
  640.             if (*(gExportPBPtr->result) = SetFPos(*(gExportPBPtr->refNum), fsFromStart, gParaStart)) 
  641.                 return(*(gExportPBPtr->result));
  642.         }
  643.     }
  644.     temp = 0;
  645.  
  646.     if (gNumParas) {
  647.         temp = (*gParaData)[gNumParas - 1].height;
  648.         if (temp < 0) temp = -temp;                        /* pictures have a negative height */
  649.         temp += (*gParaData)[gNumParas - 1].pagePos;
  650.     }
  651.     if (temp < 0 || temp >= MWPageHeight) 
  652.         temp = 0;
  653.  
  654.     height = MWPageHeight - temp;
  655.  
  656.     /* Remember SetRect uses Left, Top, Right, Bottom */
  657.     SetRect(&PB.pictureSize, 0xFFD6, 0, 0x3BE, height);
  658.     MAGICPIC.top = 'MA';
  659.     MAGICPIC.left = 'GI';
  660.     MAGICPIC.bottom = 'CP';
  661.     MAGICPIC.right = 'IC';
  662.     PH = OpenPicture(&MAGICPIC);
  663.     ClosePicture();
  664.     HLock((Handle)PH);
  665.     
  666.     gCount = sizeof(Rect);
  667.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &PB)) 
  668.         return(*(gExportPBPtr->result));                        /* Write the break */
  669.  
  670.     gCount = GetHandleSize((Handle)PH);
  671.     if (gCount & 1) gCount++;
  672.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, *PH)) 
  673.         return(*(gExportPBPtr->result));                        /* Write the break */
  674.  
  675.     DisposHandle((Handle)PH);
  676.     
  677.     SetHandleSize((Handle)gParaData, GetHandleSize((Handle)gParaData) + sizeof(ParagraphInfo));
  678.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  679.  
  680.     (*gParaData)[gNumParas].pagePos = temp;
  681.     (*gParaData)[gNumParas].filePos = gParaStart;            /* Where this paragraph started */
  682.     (*gParaData)[gNumParas].ruler = TRUE;                    /* Is a ruler record */
  683.     (*gParaData)[gNumParas].length = -gCount - sizeof(Rect);    /* Size of page break (- indicates pb) */
  684.     (*gParaData)[gNumParas].justification = *(gExportPBPtr->txtJust);
  685.     (*gParaData)[gNumParas].height = -height;
  686.  
  687.     gPHeight = 0;
  688.     gNumParas++;
  689.     SetHandleSize((Handle)gLineData, GetHandleSize((Handle)gLineData) + sizeof(LineInfo));
  690.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  691.  
  692.     (*gLineData)[gRealParas].nBytes = 0;                        /* picts have no line height */
  693.     gRealParas++;
  694.     
  695.     if (*(gExportPBPtr->result) = SetFPos(*(gExportPBPtr->refNum), fsFromLEOF, 0L)) 
  696.         return(*(gExportPBPtr->result));                        /* Set back to end of file */
  697.     
  698.     gTextLength = 0;
  699.     gParaLength = 0;
  700.     gNewParagraph = TRUE;
  701.     GetEOF(*(gExportPBPtr->refNum), &gParaStart);            /* For next paragraph */
  702.  
  703.     return(noErr);
  704. }    /*    WritePageBreak    */
  705.  
  706.  
  707. /*----------------------------------------------------------------------*/
  708. /*                                                                        */
  709. /*    InsertRuler                                                            */
  710. /*                                                                        */
  711. /*----------------------------------------------------------------------*/
  712. static short InsertRuler()
  713.  
  714. {
  715. #define RIGHTOFF 0x01FC        /* Number of pixels of average right margin */
  716.  
  717.     register short        i, pad, whichtab, tmptab;
  718.     register RulerPtr    buffer;
  719.     
  720.     SetHandleSize((Handle)gParaData, GetHandleSize((Handle)gParaData) + sizeof(ParagraphInfo));
  721.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  722.         
  723.     (*gParaData)[gNumParas].filePos = gParaStart;
  724.     (*gParaData)[gNumParas].ruler = TRUE;
  725.     (*gParaData)[gNumParas].length = sizeof(RulerInfo);
  726.     (*gParaData)[gNumParas].justification = *(gExportPBPtr->txtJust);
  727.     (*gParaData)[gNumParas].height = 0;
  728.  
  729.     pad = 0;
  730.     if (gNumParas) {
  731.         pad = (*gParaData)[gNumParas - 1].height;
  732.         if (pad < 0)
  733.             pad = -pad;                                /* pictures have a negative height */
  734.         pad += (*gParaData)[gNumParas - 1].pagePos;
  735.     }
  736.     
  737.     if (pad < 0 || pad >= MWPageHeight)
  738.         pad = 0;
  739.         
  740.     (*gParaData)[gNumParas].pagePos = pad;
  741.     gNumParas++;
  742.     
  743.     SetHandleSize((Handle)gLineData, GetHandleSize((Handle)gLineData) + sizeof(LineInfo));
  744.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  745.         
  746.     (*gLineData)[gRealParas].nBytes = 0;                /* Rulers have no line height */
  747.     gRealParas++;
  748.  
  749.     buffer = (RulerPtr) NewPtr(sizeof(RulerInfo));
  750.     
  751.     buffer->left            = FixRound((gExportPBPtr->paraFmts)[0] / 9) * 9;
  752.     buffer->right            = gColumnWidth - FixRound((gExportPBPtr->paraFmts)[2] / 9) * 9;
  753.     buffer->indentation     = FixRound((gExportPBPtr->paraFmts)[1] / 9) * 9 + buffer->left;
  754.     buffer->justification     = *(gExportPBPtr->txtJust);
  755.     if (buffer->right > RIGHTOFF)
  756.         buffer->right = RIGHTOFF;
  757.  
  758.     /* figure out line spacing */
  759.     if ((gExportPBPtr->paraFmts)[6] == -1) {
  760.         if ((gExportPBPtr->paraFmts)[3] < 0x4000)
  761.             buffer->spacing = 0;
  762.         else {
  763.             if ((gExportPBPtr->paraFmts)[3] < 0xC000)
  764.                 buffer->spacing = 1;
  765.             else
  766.                 buffer->spacing = 2;
  767.         }
  768.     } else {
  769.         if (HiWord((gExportPBPtr->paraFmts)[3]) < 15)
  770.             buffer->spacing = 0;
  771.         else {
  772.             if (HiWord((gExportPBPtr->paraFmts)[3]) < 21)
  773.                 buffer->spacing = 1;
  774.             else
  775.                 buffer->spacing = 2;
  776.         }
  777.         buffer->spacing |= 0x8000;
  778.     }
  779.     whichtab = 0;
  780.     for (i = 0; (i < 10) && ((gExportPBPtr->tabs)[i].tabIndent != -1); i++) {
  781.         tmptab = FixRound((gExportPBPtr->tabs)[i].tabIndent / 9) * 9;
  782.         
  783.         if (tmptab < buffer->left + 9)                /* No tabs outside the margins     */
  784.             continue;                                /*     or closer than 1/8 inch        */
  785.  
  786.         if (tmptab > buffer->right - 9)
  787.             break;
  788.             
  789.         if ((gExportPBPtr->tabs)[i].tabJust == textDecimal || (gExportPBPtr->tabs)[i].tabJust == textRight)
  790.             tmptab = -tmptab;
  791.             
  792.         buffer->theTabs[whichtab++] = tmptab;
  793.     }
  794.     buffer->numTabs = whichtab;
  795.     buffer->dummy = -1L;
  796.  
  797.     gCount = sizeof(RulerInfo);
  798.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, buffer)) 
  799.         return(*(gExportPBPtr->result));
  800.  
  801.     DisposPtr((Ptr)buffer);
  802.     GetEOF(*(gExportPBPtr->refNum), &gParaStart);            /* Save for the next data sent */
  803.  
  804.     return(noErr);
  805. }    /*    InsertRuler    */
  806.  
  807.  
  808. /*----------------------------------------------------------------------*/
  809. /*                                                                        */
  810. /*    FindFontSize determines if required font size is available             */
  811. /*                                                                        */
  812. /*----------------------------------------------------------------------*/
  813. static short FindFontSize(good_size)
  814. register short good_size;
  815. {
  816.     register short i;
  817.     
  818.     /* Pin to largest or smallest value if appropriate */
  819.     if (good_size >= MWSizes[MWFontSizes - 1]) return (MWSizes[MWFontSizes - 1]);
  820.     if (good_size <= MWSizes[0]) return (MWSizes[0]);
  821.     
  822.     for (i = MWFontSizes - 1; i--;) {
  823.         if (good_size == MWSizes[i]) return (MWSizes[i]);    /* If exact, return */
  824.         
  825.         if (good_size > MWSizes[i]) {                        /* We are between valid MW sizes */
  826.             if (MWSizes[i + 1] - good_size <= good_size - MWSizes[i]) 
  827.                 return (MWSizes[i + 1]);
  828.             else 
  829.                 return (MWSizes[i]);
  830.         }
  831.     }
  832.     return(MWSizes[0]);
  833. }    /*    FindFontSize    */
  834.  
  835.  
  836. /*----------------------------------------------------------------------*/
  837. /*                                                                        */
  838. /*    WriteParagraph handles output of current paragraph.                     */
  839. /*                                                                        */
  840. /*----------------------------------------------------------------------*/
  841. static short WriteParagraph()
  842. {
  843.     register unsigned char    ch;
  844.     register short            theSize, i;
  845.  
  846.     unsigned char    otherchar;
  847.     short            story;
  848.     MacWriteWindow    *wptr;
  849.  
  850.     SetHandleSize((Handle)gFormatRun, GetHandleSize((Handle)gFormatRun) + sizeof(FormatInfo));
  851.     if (*(gExportPBPtr->result) = MemError()) return(*(gExportPBPtr->result));
  852.  
  853.     (*gFormatRun)[gNumFormats].filePos = gTextLength;
  854.     theSize = FindFontSize(*(gExportPBPtr->txtSize) >> ((*(gExportPBPtr->txtFace) & textSuperior) ? 3 : 2));
  855.  
  856.     (*gFormatRun)[gNumFormats].pointSize = theSize;
  857.     (*gFormatRun)[gNumFormats].styleSet = *(gExportPBPtr->txtFace) & StyleMask;
  858.  
  859.     if (*(gExportPBPtr->txtFace) & textSuperior) (*gFormatRun)[gNumFormats].styleSet |= textSuperScript;
  860.     (*gFormatRun)[gNumFormats].fontNum = *(gExportPBPtr->txtFont);
  861.     
  862.     if (gFirstStyle) {
  863.         switch(gExportPBPtr->currentStory)
  864.         {
  865.             case rightHeaderStory:
  866.             case leftHeaderStory:
  867.             case headerStory:            story = AHeader;
  868.                                         break;
  869.             
  870.             case rightFooterStory:
  871.             case leftFooterStory:
  872.             case footerStory:            story = AFooter;
  873.                                         break;
  874.             
  875.             case mainStory:
  876.             default:                    story = TheMainDoc;
  877.                                         break;
  878.         }
  879.  
  880.         wptr = &(**MWHeader).window[story];
  881.  
  882.         wptr->activeStyle = theSize << 8;
  883.         wptr->activeStyle |= *(gExportPBPtr->txtFace) & StyleMask;
  884.         wptr->activeFont = *(gExportPBPtr->txtFont);
  885.         gFirstStyle = FALSE;
  886.     }
  887.     
  888.     gPHeight = ((theSize > gPHeight) ? theSize : gPHeight);
  889.  
  890.     gTextLength += *(gExportPBPtr->textLength);
  891.     gNumFormats++;
  892.     gParaLength += sizeof(FormatInfo);
  893.     
  894.     if (ChangeParagraph()) {
  895.         if (*(gExportPBPtr->result) = InsertRuler())
  896.             return(*(gExportPBPtr->result));
  897.         gFirstTime = FALSE;
  898.     }
  899.     if (gNewParagraph) {
  900.         gParaLength += 2;
  901.         gCount = 2;
  902.         if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, *(gExportPBPtr->textBuffer)))
  903.             return(*(gExportPBPtr->result));
  904.         gNewParagraph = FALSE;
  905.     }
  906.     /* Output the text */
  907.     for (i = 0; i < *(gExportPBPtr->textLength); i++) {
  908.         if (gNewParagraph) {
  909.             gParaLength += 2;
  910.             gCount = 2;
  911.             if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, *(gExportPBPtr->textBuffer)))
  912.                 return(*(gExportPBPtr->result));
  913.             gNewParagraph = FALSE;
  914.         }
  915.         ch = (*(gExportPBPtr->textBuffer) + i)[0];
  916.         if (ISLINECHAR(ch) || ch == floatingPict) { /* Found end of a paragraph */
  917.             switch (ch)
  918.             {
  919.                 case    newColumn:
  920.                 case    newPage:
  921.                 case    mergeBreak:
  922.                     /* Write the page break paragraph */
  923.                     *(gExportPBPtr->result) = WritePageBreak();
  924.                     break;
  925.                     
  926.                 case    floatingPict:
  927.                     /* 
  928.                     MacWrite 5.0 does not support floating pictures, so break the
  929.                     paragraph - write the picture, then start new paragraph
  930.                     */
  931.  
  932.                     /* only insert a CR if this is not a new paragraph */
  933.                     if (gParaLength > 2 + sizeof(FormatInfo))
  934.                         if (*(gExportPBPtr->result) = WriteCR()) return(*(gExportPBPtr->result));
  935.                     *(gExportPBPtr->result) = WritePict();
  936.                     break;
  937.                     
  938.                 default:
  939.                     /* If it's any other kind of page breaker, just write a CR */
  940.                     *(gExportPBPtr->result) = WriteCR();
  941.                     break;
  942.             }
  943.             if (*(gExportPBPtr->result)) return(*(gExportPBPtr->result));
  944.         } else {
  945.             if (ch == softHyphen || ISSPECIALCHAR(ch))
  946.                 gTextLength--;
  947.             else {
  948.                 otherchar = ch;
  949.                 gCount = 1;
  950.                 if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &otherchar))
  951.                     return(*(gExportPBPtr->result));
  952.                 gParaLength++;
  953.             }
  954.         }
  955.     }
  956.     return(noErr);
  957. }    /* WriteParagraph */
  958.  
  959.  
  960. /*----------------------------------------------------------------------*/
  961. /*                                                                        */
  962. /*    WriteCR outputs a “carriage return” (0x0d).                             */
  963. /*                                                                        */
  964. /*----------------------------------------------------------------------*/
  965. static short WriteCR()
  966. {
  967.     unsigned char    ch = 0x0D;
  968.  
  969.     gCount = 1;
  970.  
  971.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &ch)) 
  972.         return *(gExportPBPtr->result);
  973.  
  974.     gParaLength++;
  975.  
  976.     if (*(gExportPBPtr->result) = InsertParagraph()) 
  977.         return(*(gExportPBPtr->result));
  978.  
  979.     return(noErr);
  980. }    /* WriteCR */
  981.  
  982.  
  983. /*----------------------------------------------------------------------*/
  984. /*                                                                        */
  985. /*    LastParagraph handles clean up after import is finished.             */
  986. /*    Called from CloseStory.                                                */
  987. /*                                                                        */
  988. /*----------------------------------------------------------------------*/
  989. static short LastParagraph()
  990. {
  991.     /* Last paragraph is of zero bytes long. */
  992.  
  993.     if (gParaLength)
  994.         if (*(gExportPBPtr->result) = InsertParagraph())
  995.             return(*(gExportPBPtr->result));
  996.  
  997.     gParaLength += 2;
  998.     gCount = 2;
  999.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, *(gExportPBPtr->textBuffer))) 
  1000.         return(*(gExportPBPtr->result));
  1001.  
  1002.     gNewParagraph = FALSE;
  1003.     *(gExportPBPtr->textLength) = 0;
  1004.  
  1005.     if (*(gExportPBPtr->result) = WriteParagraph()) return(*(gExportPBPtr->result));
  1006.     if (*(gExportPBPtr->result) = InsertParagraph()) return(*(gExportPBPtr->result));
  1007.  
  1008.     return(noErr);
  1009. }    /*    LastParagraph    */
  1010.  
  1011.  
  1012. /*----------------------------------------------------------------------*/
  1013. /*                                                                        */
  1014. /*    CloseStory handles ExportCloseMain directive.                         */
  1015. /*                                                                        */
  1016. /*----------------------------------------------------------------------*/
  1017. static short CloseStory()
  1018. {
  1019.     register ParagraphPtr     paraptr;
  1020.     register LinePtr        LinePtr;
  1021.     register short            i, story;
  1022.     InfoStruct                InfoAry;
  1023.  
  1024.     if (*(gExportPBPtr->result) = LastParagraph()) return(*(gExportPBPtr->result));
  1025.     
  1026.     /* make sure that we do not exceed the max # of paras for headers & footers */
  1027.     if (gExportPBPtr->currentStory != mainStory && gNumParas - 1 >= MaxHFParas)
  1028.     {
  1029.         gNumParas = MaxHFParas;
  1030.         gRealParas = MaxHFParas - 1;
  1031.     }
  1032.  
  1033.     switch(gExportPBPtr->currentStory)
  1034.     {
  1035.         case rightHeaderStory:
  1036.         case leftHeaderStory:
  1037.         case headerStory:
  1038.         case rightFooterStory:
  1039.         case leftFooterStory:
  1040.         case footerStory:
  1041.             if (gExportPBPtr->currentStory == rightHeaderStory 
  1042.                 || gExportPBPtr->currentStory == leftHeaderStory 
  1043.                 || gExportPBPtr->currentStory == headerStory)
  1044.             {
  1045.                 story = AHeader;
  1046.                 (**MWHeader).headerPars = gNumParas;
  1047.             } else {
  1048.                 story = AFooter;
  1049.                 (**MWHeader).footerPars = gNumParas;
  1050.             }
  1051.             if (gExportPBPtr->pagePoint.v >= 0)
  1052.                 (**MWHeader).window[story].pageNumPos = *(unsigned long *)&gExportPBPtr->pagePoint;
  1053.                 
  1054.             if (gExportPBPtr->datePoint.v >= 0)
  1055.                 (**MWHeader).window[story].datePos = *(unsigned long *)&gExportPBPtr->datePoint;
  1056.                 
  1057.             if (gExportPBPtr->timePoint.v >= 0)
  1058.                 (**MWHeader).window[story].timePos = *(unsigned long *)&gExportPBPtr->timePoint;
  1059.             break;
  1060.         
  1061.         case mainStory:
  1062.             story = TheMainDoc;
  1063.             (**MWHeader).mainPars = gNumParas;
  1064.             break;
  1065.     }
  1066.  
  1067.     /* Write line height array, store position & length */
  1068.     GetEOF(*(gExportPBPtr->refNum), &((**MWHeader).window[story].lineHeightAryPos));
  1069.     (**MWHeader).window[story].lineHeightAryLength = 0;
  1070.     HLock((Handle)gLineData);
  1071.     LinePtr = *gLineData;
  1072.  
  1073.     for (i = 0; (i <= gRealParas) && !(*(gExportPBPtr->result)); i++) {
  1074.         gCount = ((LinePtr->nBytes == 0) ? 2 : 4);
  1075.         (**MWHeader).window[story].lineHeightAryLength += gCount;
  1076.         *(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, LinePtr++);
  1077.     }
  1078.     if (*(gExportPBPtr->result)) return(*(gExportPBPtr->result));
  1079.     DisposHandle((Handle)gLineData);
  1080.  
  1081.     /* Write info array */
  1082.  
  1083.     /* First set up the common variables */
  1084.     InfoAry.paraHeight = InfoAry.paraPagePosn = InfoAry.paraFmt = 0;
  1085.     InfoAry.paraHndl = 0L;        /* Handle used only by MacWrite internally */
  1086.  
  1087.     /* Now set up the info array pointer */
  1088.     GetEOF(*(gExportPBPtr->refNum), &(**MWHeader).window[story].infoAryPos);
  1089.     HLock((Handle)gParaData);
  1090.     paraptr = *gParaData;
  1091.     for (i = gNumParas; i-- && !(*(gExportPBPtr->result)); ) {
  1092.         InfoAry.paraHeight = paraptr->height;
  1093.         if (paraptr->length < 0)
  1094.             paraptr->length = -paraptr->length;
  1095.         InfoAry.Status.justCode = 0x00         /* (0x40 | paraptr->justification) */;
  1096.         InfoAry.Status.paraFilePosn = paraptr->filePos;
  1097.         InfoAry.paraLen = paraptr->length;
  1098.         InfoAry.paraPagePosn = paraptr->pagePos;
  1099.         gCount = 16;
  1100.         *(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &InfoAry);
  1101.         paraptr++;
  1102.     }
  1103.     if (*(gExportPBPtr->result)) return(*(gExportPBPtr->result));
  1104.  
  1105.     DisposHandle((Handle)gParaData);
  1106.     DisposHandle((Handle)gFormatRun);
  1107.     
  1108.     (**MWHeader).window[story].infoAryLength = gNumParas << 4;    /* gNumParas * 16 */
  1109.     return(noErr);
  1110. }    /*    CloseStory    */
  1111.  
  1112.  
  1113. /*----------------------------------------------------------------------*/
  1114. /*                                                                        */
  1115. /*    TidyUp handles clean up after export is finished.                     */
  1116. /*                                                                        */
  1117. /*----------------------------------------------------------------------*/
  1118. static short TidyUp()
  1119. {
  1120.     FreeBlock        FreeList;
  1121.     ParamBlockRec    paramblk;
  1122.     short            vRef;
  1123.  
  1124.     /* Write Free List Array */
  1125.     GetEOF(*(gExportPBPtr->refNum), &(**MWHeader).freeListPos);
  1126.     FreeList.filePos = (**MWHeader).freeListPos + 8;
  1127.     GetVRefNum(*(gExportPBPtr->refNum), &vRef);
  1128.  
  1129.     paramblk.volumeParam.ioNamePtr = NULL;
  1130.     paramblk.volumeParam.ioVRefNum = vRef;
  1131.     paramblk.volumeParam.ioVolIndex = 0;    /* Use only the vrefnum in search */
  1132.  
  1133.     PBGetVInfo(¶mblk, FALSE);
  1134.     FreeList.blockSize = (paramblk.volumeParam.ioVFrBlk * paramblk.volumeParam.ioVAlBlkSiz) 
  1135.                                     - (**MWHeader).freeListPos + 8;
  1136.     (**MWHeader).freeListLen = (**MWHeader).freeListAlloc = gCount = 8;
  1137.  
  1138.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, &FreeList)) 
  1139.         return(*(gExportPBPtr->result));
  1140.     
  1141.     SetFPos(*(gExportPBPtr->refNum), fsFromStart, 0L);
  1142.     gCount = sizeof(MacWriteHeader);
  1143.  
  1144.     if (*(gExportPBPtr->result) = FSWrite(*(gExportPBPtr->refNum), &gCount, *MWHeader)) 
  1145.         return(*(gExportPBPtr->result));
  1146.  
  1147.     DisposHandle((Handle)MWHeader);
  1148.     return(noErr);
  1149. }    /*    TidyUp    */
  1150.